home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / comm / mail / YAM23src.lha / Source / YAM_FO.c < prev    next >
C/C++ Source or Header  |  2001-05-08  |  34KB  |  932 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
  5.  Copyright (C) 2000-2001 by YAM Open Source Team
  6.  
  7.  This program is free software; you can redistribute it and/or modify
  8.  it under the terms of the GNU General Public License as published by
  9.  the Free Software Foundation; either version 2 of the License, or
  10.  (at your option) any later version.
  11.  
  12.  This program is distributed in the hope that it will be useful,
  13.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  GNU General Public License for more details.
  16.  
  17.  You should have received a copy of the GNU General Public License
  18.  along with this program; if not, write to the Free Software
  19.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.  YAM Official Support Site :  http://www.yam.ch
  22.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  23.  
  24.  $Id: YAM_FO.c,v 1.10 2001/05/08 22:27:37 damato Exp $
  25.  
  26. ***************************************************************************/
  27.  
  28. #include "YAM.h"
  29.  
  30. /* local protos */
  31. LOCAL void FO_XPKUpdateFolder(struct Folder*, int);
  32. LOCAL BOOL FO_Move(char*, char*);
  33. LOCAL BOOL FO_MoveFolderDir(struct Folder*, struct Folder*);
  34. LOCAL BOOL FO_EnterPassword(struct Folder*);
  35. LOCAL BOOL FO_FoldernameRequest(char*);
  36. LOCAL struct FO_ClassData *FO_New(void);
  37. LOCAL BOOL GetFolderByType_cmp(struct Folder*, int*);
  38. LOCAL BOOL GetFolderByName_cmp(struct Folder*, char*);
  39. LOCAL struct Folder *GetFolderByAttribute(BOOL(*)(struct Folder*,void*), void*, int*);
  40.  
  41.  
  42. /***************************************************************************
  43.  Module: Folder Configuration
  44. ***************************************************************************/
  45.  
  46. /// FO_CreateList
  47. //  Creates a linked list of all folders
  48. struct Folder **FO_CreateList(void)
  49. {
  50.    int max, i;
  51.    struct Folder **flist;
  52.    APTR lv = G->MA->GUI.NL_FOLDERS;
  53.  
  54.    get(lv, MUIA_NList_Entries, &max);
  55.    if (flist = calloc(max+1, sizeof(struct Folder *)))
  56.    {
  57.       flist[0] = (struct Folder *)max;
  58.       for (i = 0; i < max; i++) DoMethod(lv, MUIM_NList_GetEntry, i, &flist[i+1]);
  59.    }
  60.    return flist;
  61. }
  62.  
  63. ///
  64. /// FO_GetCurrentFolder
  65. //  Returns pointer to active folder
  66. struct Folder *FO_GetCurrentFolder(void)
  67. {
  68.    struct Folder *fo;
  69.    DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &fo);
  70.    return fo;
  71. }
  72.  
  73. ///
  74. /// FO_GetFolderRexx
  75. //  Finds a folder by its name, type or position
  76. struct Folder *FO_GetFolderRexx(char *arg, int *pos)
  77. {
  78.    int i, nr = 0;
  79.    struct Folder *fo = NULL, **flist;
  80.    char *p = arg;
  81.    BOOL numeric = TRUE;
  82.  
  83.    if (flist = FO_CreateList())
  84.    {
  85.       while (*p) if (!isdigit((int)*p++)) numeric = FALSE;
  86.       if (numeric) if ((i = atoi(arg)) >= 0 && i < (int)*flist) if (flist[++i]->Type != FT_SEPARATOR) nr = i;
  87.       if (!nr) for (i = 1; i <= (int)*flist; i++)
  88.          if ((!Stricmp(arg, flist[i]->Name) && flist[i]->Type != FT_SEPARATOR) ||
  89.              (!stricmp(arg, "incoming")     && flist[i]->Type == FT_INCOMING) ||
  90.              (!stricmp(arg, "outgoing")     && flist[i]->Type == FT_OUTGOING) ||
  91.              (!stricmp(arg, "sent")         && flist[i]->Type == FT_SENT) ||
  92.              (!stricmp(arg, "deleted")      && flist[i]->Type == FT_DELETED)) { nr = i; break; }
  93.       if (nr)
  94.       {
  95.          fo = flist[nr];
  96.          if (pos) *pos = --nr;
  97.       }
  98.       free(flist);
  99.    }
  100.    return fo;
  101. }
  102.  
  103. ///
  104. /// FO_GetFolderByAttribute
  105. //  Generalized find-folder function
  106. LOCAL struct Folder *GetFolderByAttribute(BOOL (*cmpf)(struct Folder*,void*), void *attr, int *pos)
  107. {
  108.    int i;
  109.    struct Folder *fo = NULL;
  110.  
  111.    for (i = 0;; i++)
  112.    {
  113.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, i, &fo);
  114.       if (!fo) break;
  115.       if (cmpf(fo,attr)) break;
  116.    }
  117.    if (pos) *pos = i;
  118.    return fo;
  119. }
  120.  
  121. ///
  122. /// FO_GetFolderByType
  123. //  Finds a folder by its type
  124. struct Folder *FO_GetFolderByType(int type, int *pos)
  125. {
  126.     return GetFolderByAttribute((BOOL (*)(struct Folder*,void*))&GetFolderByType_cmp,&type,pos);
  127. }
  128. // comparison function for FO_GetFolderByType
  129. LOCAL BOOL GetFolderByType_cmp(struct Folder *f, int *type)
  130. {
  131.     return (BOOL)(f->Type == *type);
  132. }
  133.  
  134. ///
  135. /// FO_GetFolderByName
  136. //  Finds a folder by its name
  137. struct Folder *FO_GetFolderByName(char *name, int *pos)
  138. {
  139.     return GetFolderByAttribute((BOOL (*)(struct Folder*,void*))&GetFolderByName_cmp,name,pos);
  140. }
  141. // comparison function for FO_GetFolderByName
  142. LOCAL BOOL GetFolderByName_cmp(struct Folder *f, char *name)
  143. {
  144.     return (BOOL)(!strcmp(f->Name, name) && (f->Type != FT_SEPARATOR));
  145. }
  146.  
  147.  
  148. ///
  149. /// FO_GetFolderPosition
  150. //  Gets the position of a folder in the list
  151. int FO_GetFolderPosition(struct Folder *findfo)
  152. {
  153.    int i;
  154.    struct Folder *fo = NULL;
  155.  
  156.    for (i = 0;; i++)
  157.    {
  158.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_GetEntry, i, &fo);
  159.       if (!fo) return -1;
  160.       if (fo == findfo) return i;
  161.    }
  162. }
  163.  
  164. ///
  165. /// FO_LoadConfig
  166. //  Loads folder configuration from .fconfig file
  167. BOOL FO_LoadConfig(struct Folder *fo)
  168. {
  169.    BOOL success = FALSE;
  170.    FILE *fh;
  171.    char buffer[SIZE_LARGE], fname[SIZE_PATHFILE];
  172.  
  173.    strmfp(fname, GetFolderDir(fo), ".fconfig");
  174.    if (fh = fopen(fname, "r"))
  175.    {
  176.       fgets(buffer, SIZE_LARGE, fh);
  177.       if (!strnicmp(buffer, "YFC", 3))
  178.       {
  179.          /* pick a default value */
  180.          fo->MLSignature = 1;
  181.  
  182.          while (fgets(buffer, SIZE_LARGE, fh))
  183.          {
  184.             char *p, *value;
  185.             if (value = strchr(buffer, '=')) for (++value; ISpace(*value); value++);
  186.             if (p = strpbrk(buffer,"\r\n")) *p = 0;
  187.             for (p = buffer; *p && !ISpace(*p); p++); *p = 0;
  188.             if (*buffer && value)
  189.             {
  190.                if (!stricmp(buffer, "Name"))     stccpy(fo->Name, value, SIZE_NAME);
  191.                if (!stricmp(buffer, "MaxAge"))   fo->MaxAge = atoi(value);
  192.                if (!stricmp(buffer, "Password")) stccpy(fo->Password, Decrypt(value), SIZE_PASSWORD);
  193.                if (!stricmp(buffer, "Type"))     fo->Type = atoi(value);
  194.                if (!stricmp(buffer, "XPKType"))  fo->XPKType = atoi(value);
  195.                if (!stricmp(buffer, "Sort1"))    fo->Sort[0] = atoi(value);
  196.                if (!stricmp(buffer, "Sort2"))    fo->Sort[1] = atoi(value);
  197.                if (!stricmp(buffer, "MLFromAddr"))  stccpy(fo->MLFromAddress,    value, SIZE_ADDRESS);
  198.                if (!stricmp(buffer, "MLRepToAddr")) stccpy(fo->MLReplyToAddress, value, SIZE_ADDRESS);
  199.                if (!stricmp(buffer, "MLAddress"))   stccpy(fo->MLAddress,        value, SIZE_ADDRESS);
  200.                if (!stricmp(buffer, "MLPattern"))   stccpy(fo->MLPattern,        value, SIZE_PATTERN);
  201.                if (!stricmp(buffer, "MLSignature")) fo->MLSignature = atoi(value);
  202.             }
  203.          }
  204.          success = TRUE;
  205.       }
  206.       fclose(fh);
  207.    }
  208.    return success;
  209. }
  210.  
  211. ///
  212. /// FO_SaveConfig
  213. //  Saves folder configuration to .fconfig file
  214. void FO_SaveConfig(struct Folder *fo)
  215. {
  216.    struct DateStamp ds;
  217.    char fname[SIZE_PATHFILE];
  218.    FILE *fh;
  219.  
  220.    strmfp(fname, GetFolderDir(fo), ".fconfig");
  221.    if (fh = fopen(fname, "w"))
  222.    {
  223.       fprintf(fh, "YFC1 - YAM Folder Configuration\n");
  224.       fprintf(fh, "Name        = %s\n", fo->Name);
  225.       fprintf(fh, "MaxAge      = %ld\n", fo->MaxAge);
  226.       fprintf(fh, "Password    = %s\n", Encrypt(fo->Password));
  227.       fprintf(fh, "Type        = %ld\n", fo->Type);
  228.       fprintf(fh, "XPKType     = %ld\n", fo->XPKType);
  229.       fprintf(fh, "Sort1       = %ld\n", fo->Sort[0]);
  230.       fprintf(fh, "Sort2       = %ld\n", fo->Sort[1]);
  231.       fprintf(fh, "MLFromAddr  = %s\n", fo->MLFromAddress);
  232.       fprintf(fh, "MLRepToAddr = %s\n", fo->MLReplyToAddress);
  233.       fprintf(fh, "MLPattern   = %s\n", fo->MLPattern);
  234.       fprintf(fh, "MLAddress   = %s\n", fo->MLAddress);
  235.       fprintf(fh, "MLSignature = %ld\n", fo->MLSignature);
  236.       fclose(fh);
  237.       strmfp(fname, GetFolderDir(fo), ".index");
  238.       if (!(fo->Flags&FOFL_MODIFY)) SetFileDate(fname, DateStamp(&ds));
  239.    }
  240.    else ER_NewError(GetStr(MSG_ER_CantCreateFile), fname, NULL);
  241. }
  242.  
  243. ///
  244. /// FO_NewFolder
  245. //  Initializes a new folder and creates its directory
  246. struct Folder *FO_NewFolder(int type, char *path, char *name)
  247. {
  248.    struct Folder *folder = calloc(1, sizeof(struct Folder));
  249.    folder->Sort[0] = 1;
  250.    folder->Sort[1] = 3;
  251.    folder->Type = type;
  252.    stccpy(folder->Path, path, SIZE_PATH);
  253.    stccpy(folder->Name, name, SIZE_NAME);
  254.    if (CreateDirectory(GetFolderDir(folder))) return folder;
  255.    free(folder);
  256.    return NULL;
  257. }
  258.  
  259. ///
  260. /// FO_CreateFolder
  261. //  Adds a new entry to the folder list
  262. BOOL FO_CreateFolder(int type, char *path, char *name)
  263. {
  264.    struct Folder *folder = FO_NewFolder(type, path, name);
  265.    if (folder)
  266.    {
  267.       DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_InsertSingle, folder, MUIV_NList_Insert_Bottom);
  268.       FO_SaveConfig(folder);
  269.       free(folder);
  270.       return TRUE;
  271.    }
  272.    return FALSE;
  273. }
  274.  
  275. ///
  276. /// FO_LoadTree
  277. //  Loads folder list from a file
  278. BOOL FO_LoadTree(char *fname)
  279. {
  280.    static struct Folder fo;
  281.    BOOL success = FALSE;
  282.    char buffer[SIZE_LARGE];
  283.    int nested = 0, i = 0;
  284.    FILE *fh;
  285.    APTR lv = G->MA->GUI.NL_FOLDERS;
  286.    
  287.    if (fh = fopen(fname, "r"))
  288.    {
  289.       GetLine(fh, buffer, sizeof(buffer));
  290.       if (!strncmp(buffer, "YFO", 3))
  291.       {
  292.          DoMethod(lv, MUIM_NList_Clear);
  293.          set(lv, MUIA_NList_Quiet, TRUE);
  294.          while (GetLine(fh, buffer, sizeof(buffer)))
  295.          {
  296.             clear(&fo, sizeof(struct Folder));
  297.             if (!strncmp(buffer, "@FOLDER", 7))
  298.             {
  299.                fo.Type = FT_CUSTOM;
  300.                fo.Sort[0] = 1; fo.Sort[1] = 3;
  301.                stccpy(fo.Name, Trim(&buffer[8]),SIZE_NAME);
  302.                stccpy(fo.Path, Trim(GetLine(fh, buffer, sizeof(buffer))), SIZE_PATH);
  303.                if (CreateDirectory(GetFolderDir(&fo)))
  304.                {
  305.                   if (!FO_LoadConfig(&fo))
  306.                   {
  307.                      if (!stricmp(FilePart(fo.Path), FolderNames[0])) fo.Type = FT_INCOMING;
  308.                      if (!stricmp(FilePart(fo.Path), FolderNames[1])) fo.Type = FT_OUTGOING;
  309.                      if (!stricmp(FilePart(fo.Path), FolderNames[2])) fo.Type = FT_SENT;
  310.                      if (!stricmp(FilePart(fo.Path), FolderNames[3])) fo.Type = FT_DELETED;
  311.                      FO_SaveConfig(&fo);
  312.                   }
  313.                   fo.SortIndex = i++;
  314.                   DoMethod(lv, MUIM_NList_InsertSingle, &fo, MUIV_NList_Insert_Bottom);
  315.                }
  316.                do if (!strcmp(buffer, "@ENDFOLDER")) break;
  317.                while (GetLine(fh, buffer, sizeof(buffer)));
  318.             }
  319.             else if (!strncmp(buffer, "@SEPARATOR", 10))
  320.             {
  321.                fo.Type = FT_SEPARATOR;
  322.                stccpy(fo.Name, Trim(&buffer[11]), SIZE_NAME);
  323.                do if (!strcmp(buffer, "@ENDSEPARATOR")) break;
  324.                while (GetLine(fh, buffer, sizeof(buffer)));
  325.                fo.SortIndex = i++;
  326.                DoMethod(lv, MUIM_NList_InsertSingle, &fo, MUIV_NList_Insert_Bottom);
  327.             }
  328.             else if (!strncmp(buffer, "@GROUP", 6))  /* not yet implemented */
  329.             {
  330.                fo.Type = FT_GROUP;
  331.                stccpy(fo.Name, Trim(&buffer[7]), SIZE_NAME);
  332.                nested++;
  333.             }
  334.             else if (!strcmp(buffer,"@ENDGROUP"))
  335.             {
  336.                nested--;
  337.             }
  338.          }
  339.          set(lv, MUIA_NList_Quiet, FALSE);
  340.       }
  341.       fclose(fh);
  342.       success = TRUE;
  343.    }
  344.    return success;
  345. }
  346.  
  347. ///
  348. /// FO_SaveTree
  349. //  Saves folder list to a file
  350. BOOL FO_SaveTree(char *fname)
  351. {
  352.    BOOL success = TRUE;
  353.    struct Folder *fo;
  354.    FILE *fh;
  355.    APTR lv = G->MA->GUI.NL_FOLDERS;
  356.    int i;
  357.  
  358.    if (fh = fopen(fname, "w"))
  359.    {
  360.       fputs("YFO1 - YAM Folders\n", fh);
  361.       for (i = 0;; i++)
  362.       {
  363.          DoMethod(lv, MUIM_NList_GetEntry, i, &fo);
  364.          if (!fo) break;
  365.          fo->SortIndex = i;
  366.          switch (fo->Type)
  367.          {
  368.             case FT_SEPARATOR:  fprintf(fh, "@SEPARATOR %s\n@ENDSEPARATOR\n", fo->Name);
  369.                                 break;
  370.             case FT_GROUP:      fprintf(fh, "@GROUP %s\n", fo->Name);   /* not yet implemented */
  371.                                 fputs("@ENDGROUP\n", fh);
  372.                                 break;
  373.             default:            fprintf(fh, "@FOLDER %s\n%s\n@ENDFOLDER\n", fo->Name, fo->Path);
  374.                                 break;
  375.          }
  376.       }
  377.       fclose(fh);
  378.       success = TRUE;
  379.    }
  380.    else ER_NewError(GetStr(MSG_ER_CantCreateFile), fname, NULL);
  381.    return success;
  382. }
  383.  
  384. ///
  385. /// FO_XPKUpdateFolder
  386. //  Updates compression mode for a folder
  387. LOCAL void FO_XPKUpdateFolder(struct Folder *fo, int oldtype)
  388. {
  389.    if (fo->XPKType != oldtype)
  390.    {
  391.       struct Mail *mail;
  392.       int i;
  393.       Busy(GetStr(MSG_BusyUncompressingFO), "", 0, fo->Total);
  394.       for (i = 0, mail = fo->Messages; mail; mail = mail->Next, i++)
  395.       {
  396.          Busy(NULL, NULL, i, 0);
  397.          RepackMailFile(mail, fo->XPKType, fo->Password);
  398.       }
  399.       BusyEnd;
  400.    }
  401. }
  402.  
  403. ///
  404. /// FO_Move
  405. //  Moves a folder directory to a new destination
  406. LOCAL BOOL FO_Move(char *srcbuf, char *dstbuf)
  407. {
  408.    if (!RenameFile(srcbuf, dstbuf)) if (!CopyFile(dstbuf, 0, srcbuf, 0)) return FALSE;
  409.    return TRUE;
  410. }
  411.  
  412. ///
  413. /// FO_MoveFolderDir
  414. //  Moves a folder to a new directory
  415. LOCAL BOOL FO_MoveFolderDir(struct Folder *fo, struct Folder *oldfo)
  416. {
  417.    struct Mail *mail;
  418.    char srcbuf[SIZE_PATHFILE], dstbuf[SIZE_PATHFILE];
  419.    BOOL success = TRUE;
  420.    int i;
  421.    Busy(GetStr(MSG_BusyMoving), itoa(fo->Total), 0, fo->Total);
  422.    strcpy(srcbuf, GetFolderDir(oldfo));
  423.    strcpy(dstbuf, GetFolderDir(fo));
  424.    for (i = 0, mail = fo->Messages; mail && success; mail = mail->Next, i++)
  425.    {
  426.       Busy(NULL, NULL, i, 0);
  427.       GetMailFile(dstbuf, fo, mail);
  428.       GetMailFile(srcbuf, oldfo, mail);
  429.       if (!FO_Move(srcbuf, dstbuf)) success = FALSE;
  430.       else RepackMailFile(mail, fo->XPKType, fo->Password);
  431.    }
  432.    if (success)
  433.    {
  434.       strmfp(srcbuf, GetFolderDir(oldfo), ".index");
  435.       strmfp(dstbuf, GetFolderDir(fo), ".index");
  436.       FO_Move(srcbuf, dstbuf);
  437.       DeleteMailDir(GetFolderDir(oldfo), FALSE);
  438.    }
  439.    BusyEnd;
  440.    return success;
  441. }
  442.  
  443. ///
  444. /// FO_EnterPassword
  445. //  Sets password for a protected folder
  446. LOCAL BOOL FO_EnterPassword(struct Folder *fo)
  447. {
  448.    char passwd[SIZE_PASSWORD], passwd2[SIZE_PASSWORD];
  449.  
  450.    for (*passwd = 0;;)
  451.    {
  452.       *passwd = *passwd2 = 0;
  453.       if (!StringRequest(passwd, SIZE_PASSWORD, GetStr(MSG_Folder), GetStr(MSG_CO_ChangeFolderPass), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, G->FO->GUI.WI)) return FALSE;
  454.       if (*passwd) if (!StringRequest(passwd2, SIZE_PASSWORD, GetStr(MSG_Folder), GetStr(MSG_CO_RetypePass), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), TRUE, G->FO->GUI.WI)) return FALSE;
  455.       if (!Stricmp(passwd, passwd2)) break; else DisplayBeep(NULL);
  456.    }
  457.    if (!*passwd) return FALSE;
  458.    strcpy(fo->Password, passwd);
  459.    return TRUE;
  460. }
  461.  
  462. ///
  463. /// FO_FoldernameRequest
  464. //  Asks user for a folder name and path
  465. LOCAL BOOL FO_FoldernameRequest(char *string)
  466. {
  467.    char *path;
  468.    APTR bt_okay, bt_cancel, wi, st_pa, st_di;
  469.    int ret_code = -1;
  470.  
  471.    wi = WindowObject,
  472.       MUIA_Window_Title, GetStr(MSG_Folder),
  473.       MUIA_Window_RefWindow, G->MA->GUI.WI,
  474.       MUIA_Window_LeftEdge, MUIV_Window_LeftEdge_Centered,
  475.       MUIA_Window_TopEdge, MUIV_Window_TopEdge_Centered,
  476.       MUIA_Window_ID, MAKE_ID('N','F','R','Q'),
  477.       WindowContents, VGroup,
  478.          Child, VGroup,
  479.             GroupFrame,
  480.             MUIA_Background, MUII_GroupBack,
  481.             Child, LLabel(GetStr(MSG_CO_SelectDir)),
  482.             Child, ColGroup(2),
  483.                Child, Label2(GetStr(MSG_Path)),
  484.                Child, PopaslObject,
  485.                   MUIA_Popasl_Type, ASL_FileRequest,
  486.                   MUIA_Popstring_String, st_pa = MakeString(SIZE_PATH, ""),
  487.                   MUIA_Popstring_Button, PopButton(MUII_PopDrawer),
  488.                   ASLFR_DrawersOnly, TRUE,
  489.                End,
  490.                Child, Label2(GetStr(MSG_Directory)),
  491.                Child, st_di = MakeString(SIZE_FILE, ""),
  492.             End,
  493.          End,
  494.          Child, ColGroup(2),
  495.             Child, bt_okay = MakeButton(GetStr(MSG_Okay)),
  496.             Child, bt_cancel = MakeButton(GetStr(MSG_Cancel)),
  497.          End,
  498.       End,
  499.    End;
  500.    if (wi)
  501.    {
  502.       setstring(st_pa, G->MA_MailDir);
  503.       setstring(st_di, string);
  504.       set(st_di, MUIA_String_Reject, " \";:/#?(|)");
  505.       set(wi, MUIA_Window_ActiveObject, st_di);
  506.       set(G->App, MUIA_Application_Sleep, TRUE);
  507.       DoMethod(G->App, OM_ADDMEMBER, wi);
  508.       DoMethod(bt_okay  , MUIM_Notify, MUIA_Pressed, FALSE, G->App, 2, MUIM_Application_ReturnID, 1);
  509.       DoMethod(bt_cancel, MUIM_Notify, MUIA_Pressed, FALSE, G->App, 2, MUIM_Application_ReturnID, 3);
  510.       DoMethod(st_di, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, G->App, 2, MUIM_Application_ReturnID, 1);
  511.       DoMethod(wi, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, G->App, 2, MUIM_Application_ReturnID, 3);
  512.       if (!SafeOpenWindow(wi)) ret_code = 0;
  513.       while (ret_code == -1)
  514.       {
  515.          ULONG signals;
  516.          switch (DoMethod(G->App, MUIM_Application_Input, &signals))
  517.          {
  518.             case 1: if (*(GetMUIStringPtr(st_di))) ret_code = 1;
  519.                     break;
  520.             case 3: ret_code = 0; break;
  521.          }
  522.          if (ret_code == -1 && signals) Wait(signals);
  523.       }
  524.       path = GetMUIStringPtr(st_pa);
  525.       if (ret_code > 0)
  526.          if (!stricmp(path, G->MA_MailDir)) GetMUIString(string, st_di);
  527.          else strmfp(string, path, GetMUIStringPtr(st_di));
  528.       DoMethod(G->App, OM_REMMEMBER, wi);
  529.       set(G->App, MUIA_Application_Sleep, FALSE);
  530.    }
  531.    return (BOOL)ret_code;
  532. }
  533.  
  534. ///
  535. /// FO_GetFolder
  536. //  Fills form with data from folder structure
  537. void FO_GetFolder(struct Folder *folder, BOOL existing)
  538. {
  539.    struct FO_GUIData *gui = &G->FO->GUI;
  540.    BOOL isdefault = (folder->Type != FT_CUSTOM && folder->Type != FT_CUSTOMSENT && folder->Type != FT_CUSTOMMIXED);
  541.    static int type2cycle[9] = { 0,0,1,1,2,-1,1,2,-1 };
  542.    int i;
  543.  
  544.    set(gui->ST_FNAME, MUIA_String_Contents, folder->Name);
  545.    set(gui->TX_FPATH, MUIA_Text_Contents, folder->Path);
  546.    set(gui->ST_MAXAGE, MUIA_String_Integer, folder->MaxAge);
  547.    set(gui->CY_FTYPE, MUIA_Cycle_Active, type2cycle[folder->Type]);
  548.    set(gui->CY_FMODE, MUIA_Cycle_Active, folder->XPKType);
  549.    for (i = 0; i < 2; i++)
  550.    {
  551.       set(gui->CY_SORT[i], MUIA_Cycle_Active, ABS(folder->Sort[i])-1);
  552.       set(gui->CH_REVERSE[i], MUIA_Selected, folder->Sort[i] < 0);
  553.    }
  554.    set(gui->ST_MLADDRESS,        MUIA_String_Contents, folder->MLAddress);
  555.    set(gui->ST_MLPATTERN,        MUIA_String_Contents, folder->MLPattern);
  556.    set(gui->ST_MLFROMADDRESS,    MUIA_String_Contents, folder->MLFromAddress);
  557.    set(gui->ST_MLREPLYTOADDRESS, MUIA_String_Contents, folder->MLReplyToAddress);
  558.    set(gui->CY_MLSIGNATURE,          MUIA_Cycle_Active,    folder->MLSignature);
  559.    set(gui->CY_FTYPE, MUIA_Disabled, isdefault);
  560.    set(gui->CY_FMODE, MUIA_Disabled, isdefault || existing);
  561.    set(gui->BT_MOVE, MUIA_Disabled, existing);
  562. }
  563.  
  564. ///
  565. /// FO_PutFolder
  566. //  Updates folder structure with form data
  567. void FO_PutFolder(struct Folder *folder)
  568. {
  569.    struct FO_GUIData *gui = &G->FO->GUI;
  570.    BOOL isdefault = (folder->Type != FT_CUSTOM && folder->Type != FT_CUSTOMSENT && folder->Type != FT_CUSTOMMIXED);
  571.    static int cycle2type[3] = { FT_CUSTOM,FT_CUSTOMSENT,FT_CUSTOMMIXED };
  572.    int i;
  573.  
  574.    GetMUIString(folder->Name, gui->ST_FNAME);
  575.    GetMUIText(folder->Path, gui->TX_FPATH);
  576.    folder->MaxAge = GetMUIInteger(gui->ST_MAXAGE);
  577.    if (!isdefault)
  578.    {
  579.       folder->Type = cycle2type[GetMUICycle(gui->CY_FTYPE)];
  580.       folder->XPKType = GetMUICycle(gui->CY_FMODE);
  581.    }
  582.    for (i = 0; i < 2; i++)
  583.    {
  584.       folder->Sort[i] = GetMUICycle(gui->CY_SORT[i])+1;
  585.       if (GetMUICheck(gui->CH_REVERSE[i])) folder->Sort[i] = -folder->Sort[i];
  586.    }
  587.    GetMUIString(folder->MLPattern,        gui->ST_MLPATTERN);
  588.    GetMUIString(folder->MLAddress,        gui->ST_MLADDRESS);
  589.    GetMUIString(folder->MLFromAddress,    gui->ST_MLFROMADDRESS);
  590.    GetMUIString(folder->MLReplyToAddress, gui->ST_MLREPLYTOADDRESS);
  591.    folder->MLSignature = GetMUICycle(gui->CY_MLSIGNATURE);
  592. }
  593.  
  594. ///
  595. /// FO_NewSeparatorFunc
  596. //  Creates a new separator
  597. void SAVEDS FO_NewSeparatorFunc(void)
  598. {
  599.    struct Folder folder;
  600.    clear(&folder, sizeof(struct Folder));
  601.    folder.Type = FT_SEPARATOR;
  602.    if (StringRequest(folder.Name, SIZE_NAME, GetStr(MSG_MA_NewSeparator), GetStr(MSG_FO_NewSepReq), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), FALSE, G->MA->GUI.WI))
  603.    {
  604.       int pos;
  605.       APTR lv = G->MA->GUI.NL_FOLDERS;
  606.       get(lv, MUIA_NList_Active, &pos);
  607.       DoMethod(lv, MUIM_NList_InsertSingle, &folder, ++pos);
  608.    }
  609. }
  610. MakeHook(FO_NewSeparatorHook, FO_NewSeparatorFunc);
  611.  
  612. ///
  613. /// FO_NewFolderFunc
  614. //  Creates a new folder
  615. void SAVEDS FO_NewFolderFunc(void)
  616. {
  617.    int mode = MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_NewFolder), GetStr(MSG_FO_NewFolderGads), GetStr(MSG_FO_NewFolderReq));
  618.    static struct Folder folder;
  619.  
  620.    clear(&folder, sizeof(struct Folder));
  621.    folder.Sort[0] = 1; folder.Sort[1] = 3; folder.Type = FT_CUSTOM;
  622.    switch (mode)
  623.    {
  624.       case 0: return;
  625.       case 1: if (!FO_FoldernameRequest(folder.Path)) return;
  626.               stccpy(folder.Name, FilePart(folder.Path), SIZE_NAME);
  627.               break;
  628.       case 2: memcpy(&folder, FO_GetCurrentFolder(), sizeof(struct Folder));
  629.               if (folder.Type == FT_SEPARATOR) { FO_NewSeparatorFunc(); return; }
  630.               else if (folder.Type == FT_INCOMING || folder.Type == FT_DELETED) folder.Type = FT_CUSTOM;
  631.               else if (folder.Type == FT_OUTGOING || folder.Type == FT_SENT) folder.Type = FT_CUSTOMSENT;
  632.               *folder.Path = 0;
  633.               if (!FO_FoldernameRequest(folder.Path)) return;
  634.               stccpy(folder.Name, FilePart(folder.Path), SIZE_NAME);
  635.               break;
  636.       case 3: if (!ReqFile(ASL_FOLDER, G->MA->GUI.WI, GetStr(MSG_FO_SelectDir), 4, G->MA_MailDir, "")) return;
  637.               stccpy(folder.Path, G->ASLReq[ASL_FOLDER]->fr_Drawer, SIZE_PATH);
  638.               FO_LoadConfig(&folder);
  639.               break;
  640.    }
  641.    if (!G->FO)
  642.    {
  643.       if (!(G->FO = FO_New())) return;
  644.       if (!SafeOpenWindow(G->FO->GUI.WI)) { DisposeModulePush(&G->FO); return; }
  645.    }
  646.    FO_GetFolder(&folder, mode==3);
  647. }
  648. MakeHook(FO_NewFolderHook, FO_NewFolderFunc);
  649.  
  650. ///
  651. /// FO_EditFolderFunc
  652. //  Opens folder window to edit the settings of the active folder
  653. void SAVEDS FO_EditFolderFunc(void)
  654. {
  655.    struct Folder *folder = FO_GetCurrentFolder();
  656.    if (folder->Type == FT_SEPARATOR)
  657.    {
  658.       if (StringRequest(folder->Name, SIZE_NAME, GetStr(MSG_FO_EditFolder), GetStr(MSG_FO_NewSepReq), GetStr(MSG_Okay), NULL, GetStr(MSG_Cancel), FALSE, G->MA->GUI.WI))
  659.          DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  660.    }
  661.    else
  662.    {
  663.       if (!G->FO)
  664.       {
  665.          if (!(G->FO = FO_New())) return;
  666.          if (!SafeOpenWindow(G->FO->GUI.WI)) { DisposeModulePush(&G->FO); return; }
  667.       }
  668.       FO_GetFolder(G->FO->EditFolder = folder, FALSE);
  669.    }
  670. }
  671. MakeHook(FO_EditFolderHook, FO_EditFolderFunc);
  672.  
  673. ///
  674. /// FO_DeleteFolderFunc
  675. //  Removes the active folder
  676. void SAVEDS FO_DeleteFolderFunc(void)
  677. {
  678.    APTR lv = G->MA->GUI.NL_FOLDERS;
  679.    struct Folder *f, *folder = FO_GetCurrentFolder();
  680.    int i, pos, used = 0;
  681.    get(lv, MUIA_NList_Active, &pos);
  682.  
  683.    for (i = 0; ; i++)
  684.    {
  685.       DoMethod(lv, MUIM_NList_GetEntry, i, &f);
  686.       if (!f) break; else if (!stricmp(f->Path, folder->Path)) used++;
  687.    }
  688.    switch (folder->Type)
  689.    {
  690.       case FT_CUSTOM:
  691.       case FT_CUSTOMSENT:
  692.       case FT_CUSTOMMIXED: if (used < 2)
  693.                            {
  694.                               if (!MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_YesNoReq), GetStr(MSG_CO_ConfirmDelete))) return;
  695.                               DeleteMailDir(GetFolderDir(folder), FALSE);
  696.                            }
  697.                            ClearMailList(folder, TRUE);
  698.       case FT_SEPARATOR:   DoMethod(lv, MUIM_NList_Remove, pos);
  699.                            FO_SaveTree(CreateFilename(".folders"));
  700.                            break;
  701.       default:             break;
  702.    }
  703. }
  704. MakeHook(FO_DeleteFolderHook, FO_DeleteFolderFunc);
  705.  
  706. ///
  707. /// FO_MoveFunc
  708. //  Asks user for the new destination
  709. void SAVEDS FO_MoveFunc(void)
  710. {
  711.    char path[SIZE_PATH];
  712.    GetMUIText(path, G->FO->GUI.TX_FPATH);
  713.    if (FO_FoldernameRequest(path)) set(G->FO->GUI.TX_FPATH, MUIA_Text_Contents, path);
  714. }
  715. MakeHook(FO_MoveHook, FO_MoveFunc);
  716.  
  717. ///
  718. /// FO_CloseFunc
  719. //  Closes folder configuration window
  720. void SAVEDS FO_CloseFunc(void)
  721. {
  722.    DisposeModulePush(&G->FO);
  723. }
  724. MakeHook(FO_CloseHook, FO_CloseFunc);
  725.  
  726. ///
  727. /// FO_SaveFunc
  728. //  Saves modified folder configuration
  729. void SAVEDS FO_SaveFunc(void)
  730. {
  731.    struct FO_GUIData *gui = &G->FO->GUI;
  732.    APTR lv = G->MA->GUI.NL_FOLDERS;
  733.    struct Folder folder, *oldfolder = G->FO->EditFolder;
  734.    BOOL success = FALSE;
  735.  
  736.    if (oldfolder)
  737.    {
  738.       memcpy(&folder, oldfolder, sizeof(struct Folder));
  739.       FO_PutFolder(&folder);
  740.       if (stricmp(oldfolder->Path, folder.Path))
  741.       {
  742.          if (Rename(oldfolder->Path, folder.Path)) strcpy(oldfolder->Path, folder.Path);
  743.          else
  744.             if (CreateDirectory(GetFolderDir(&folder))) if (FO_MoveFolderDir(&folder, oldfolder))
  745.                strcpy(oldfolder->Path, folder.Path);
  746.       }
  747.       strcpy(oldfolder->Name, folder.Name);
  748.       strcpy(oldfolder->MLFromAddress,    folder.MLFromAddress);
  749.       strcpy(oldfolder->MLReplyToAddress, folder.MLReplyToAddress);
  750.       strcpy(oldfolder->MLAddress,        folder.MLAddress);
  751.       strcpy(oldfolder->MLPattern,        folder.MLPattern);
  752.       oldfolder->MLSignature = folder.MLSignature;
  753.       oldfolder->Sort[0] = folder.Sort[0];
  754.       oldfolder->Sort[1] = folder.Sort[1];
  755.       oldfolder->MaxAge  = folder.MaxAge;
  756.       if (!GetMUI(gui->CY_FTYPE, MUIA_Disabled))
  757.       {
  758.          int oldxpk = oldfolder->XPKType, newxpk = folder.XPKType;
  759.          BOOL changed = TRUE;
  760.          if (oldxpk == newxpk || (newxpk > 1 && !XpkBase)) changed = FALSE;
  761.          else if (!(newxpk&1) && (oldxpk&1) && oldfolder->LoadedMode != 2) changed = MA_PromptFolderPassword(&folder, gui->WI);
  762.          else if ((newxpk&1) && !(oldxpk&1)) changed = FO_EnterPassword(&folder);
  763.          if ((newxpk&1) && (oldxpk&1)) strcpy(folder.Password, oldfolder->Password);
  764.          if (changed)
  765.          {
  766.             if (!(newxpk&1)) *folder.Password = 0;
  767.             FO_XPKUpdateFolder(&folder, oldxpk);
  768.             oldfolder->XPKType = newxpk;
  769.             strcpy(oldfolder->Password, folder.Password);
  770.          }
  771.          oldfolder->Type = folder.Type;
  772.       }
  773.       set(gui->WI, MUIA_Window_Open, FALSE);
  774.       DoMethod(lv, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  775.       FO_SaveConfig(&folder);
  776.       success = TRUE;
  777.    }
  778.    else
  779.    {
  780.       clear(&folder, sizeof(struct Folder));
  781.       FO_PutFolder(&folder);
  782.       if (folder.XPKType&1) if (!FO_EnterPassword(&folder)) folder.XPKType &= ~1;
  783.       set(gui->WI, MUIA_Window_Open, FALSE);
  784.       if (CreateDirectory(GetFolderDir(&folder)))
  785.       {
  786.          int pos;
  787.          get(lv, MUIA_NList_Active, &pos);
  788.          DoMethod(lv, MUIM_NList_InsertSingle, &folder, ++pos);
  789.          FO_SaveConfig(&folder);
  790.          success = TRUE;
  791.       }
  792.    }
  793.    if (success)
  794.    {
  795.       MA_SetSortFlag();
  796.       DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Sort);
  797.       MA_ChangeFolder(FO_GetFolderByName(folder.Name, NULL));
  798.       FO_SaveTree(CreateFilename(".folders"));
  799.    }
  800.    DisposeModulePush(&G->FO);
  801. }
  802. MakeHook(FO_SaveHook, FO_SaveFunc);
  803.  
  804. ///
  805. /// FO_SetOrderFunc
  806. //  Saves or resets folder order
  807. void SAVEDS ASM FO_SetOrderFunc(REG(a1,int *arg))
  808. {
  809.    switch (*arg)
  810.    {
  811.       case SO_SAVE:  FO_SaveTree(CreateFilename(".folders")); break;
  812.       case SO_RESET: DoMethod(G->MA->GUI.NL_FOLDERS, MUIM_NList_Sort2, 10, 0); break;
  813.    }
  814. }
  815. MakeHook(FO_SetOrderHook, FO_SetOrderFunc);
  816. ///
  817.  
  818. /// FO_New
  819. //  Creates folder configuration window
  820. LOCAL struct FO_ClassData *FO_New(void)
  821. {
  822.    struct FO_ClassData *data;
  823.  
  824.    if (data = calloc(1, sizeof(struct FO_ClassData)))
  825.    {
  826.       APTR bt_okay, bt_cancel;
  827.       static char *ftypes[4], *fmodes[5], *sortopt[8], *fsignat[5];
  828.             fsignat[0] = GetStr(MSG_WR_NoSig);
  829.             fsignat[1] = GetStr(MSG_WR_DefSig);
  830.             fsignat[2] = GetStr(MSG_WR_AltSig1);
  831.             fsignat[3] = GetStr(MSG_WR_AltSig2);
  832.             fsignat[4] = NULL;
  833.       sortopt[0] = GetStr(MSG_FO_MessageDate);
  834.       sortopt[1] = GetStr(MSG_FO_DateRecvd);
  835.       sortopt[2] = GetStr(MSG_Sender);
  836.       sortopt[3] = GetStr(MSG_Recipient);
  837.       sortopt[4] = GetStr(MSG_Subject);
  838.       sortopt[5] = GetStr(MSG_Size);
  839.       sortopt[6] = GetStr(MSG_Status);
  840.       sortopt[7] = NULL;
  841.       fmodes[0]  = GetStr(MSG_FO_FMNormal);
  842.       fmodes[1]  = GetStr(MSG_FO_FMSimple);
  843.       fmodes[2]  = GetStr(MSG_FO_FMPack);
  844.       fmodes[3]  = GetStr(MSG_FO_FMEncPack);
  845.       fmodes[4]  = NULL;
  846.       ftypes[0]  = GetStr(MSG_FO_FTRcvdMail);
  847.       ftypes[1]  = GetStr(MSG_FO_FTSentMail);
  848.       ftypes[2]  = GetStr(MSG_FO_FTBothMail);
  849.       ftypes[3]  = NULL;
  850.       data->GUI.WI = WindowObject,
  851.          MUIA_Window_Title, GetStr(MSG_FO_EditFolder),
  852.          MUIA_HelpNode, "FO_W",
  853.          MUIA_Window_ID, MAKE_ID('F','O','L','D'),
  854.          WindowContents, VGroup,
  855.             Child, ColGroup(2), GroupFrameT(GetStr(MSG_FO_Properties)),
  856.                Child, Label2(GetStr(MSG_CO_Name)),
  857.                Child, data->GUI.ST_FNAME = MakeString(SIZE_NAME,GetStr(MSG_CO_Name)),
  858.                Child, Label2(GetStr(MSG_Path)),
  859.                Child, HGroup,
  860.                   MUIA_Group_HorizSpacing, 0,
  861.                   Child, data->GUI.TX_FPATH = TextObject, MUIA_Background, MUII_TextBack, MUIA_Frame, MUIV_Frame_Text, End,
  862.                   Child, data->GUI.BT_MOVE = PopButton(MUII_PopDrawer),
  863.                End,
  864.                Child, Label2(GetStr(MSG_FO_MaxAge)),
  865.                Child, data->GUI.ST_MAXAGE = MakeInteger(4,GetStr(MSG_FO_MaxAge)),
  866.                Child, Label1(GetStr(MSG_FO_FolderType)),
  867.                Child, data->GUI.CY_FTYPE = MakeCycle(ftypes,GetStr(MSG_FO_FolderType)),
  868.                Child, Label1(GetStr(MSG_FO_FolderMode)),
  869.                Child, data->GUI.CY_FMODE = MakeCycle(fmodes,GetStr(MSG_FO_FolderMode)),
  870.                Child, Label1(GetStr(MSG_FO_SortBy)),
  871.                Child, HGroup,
  872.                   Child, data->GUI.CY_SORT[0] = MakeCycle(sortopt,GetStr(MSG_FO_SortBy)),
  873.                   Child, data->GUI.CH_REVERSE[0] = MakeCheck(GetStr(MSG_FO_Reverse)),
  874.                   Child, LLabel1(GetStr(MSG_FO_Reverse)),
  875.                End,
  876.                Child, Label1(GetStr(MSG_FO_ThenBy)),
  877.                Child, HGroup,
  878.                   Child, data->GUI.CY_SORT[1] = MakeCycle(sortopt,GetStr(MSG_FO_ThenBy)),
  879.                   Child, data->GUI.CH_REVERSE[1] = MakeCheck(GetStr(MSG_FO_Reverse)),
  880.                   Child, LLabel1(GetStr(MSG_FO_Reverse)),
  881.                End,
  882.             End,
  883.             Child, ColGroup(2), GroupFrameT(GetStr(MSG_FO_MLSupport)),
  884.                Child, Label2(GetStr(MSG_FO_ToPattern)),
  885.                Child, data->GUI.ST_MLPATTERN = MakeString(SIZE_PATTERN,GetStr(MSG_FO_ToPattern)),
  886.                Child, Label2(GetStr(MSG_FO_ToAddress)),
  887.                Child, data->GUI.ST_MLADDRESS = MakeString(SIZE_ADDRESS,GetStr(MSG_FO_ToAddress)),
  888.                Child, Label2(GetStr(MSG_FO_FromAddress)),
  889.                Child, data->GUI.ST_MLFROMADDRESS = MakeString(SIZE_ADDRESS,GetStr(MSG_FO_FromAddress)),
  890.                Child, Label2(GetStr(MSG_FO_ReplyToAddress)),
  891.                Child, data->GUI.ST_MLREPLYTOADDRESS = MakeString(SIZE_ADDRESS,GetStr(MSG_FO_ReplyToAddress)),
  892.                Child, Label1(GetStr(MSG_WR_Signature)),
  893.                Child, data->GUI.CY_MLSIGNATURE = MakeCycle(fsignat, GetStr(MSG_WR_Signature)),
  894.             End,
  895.             Child, ColGroup(3),
  896.                Child, bt_okay = MakeButton(GetStr(MSG_Okay)),
  897.                Child, HSpace(0),
  898.                Child, bt_cancel = MakeButton(GetStr(MSG_Cancel)),
  899.             End,
  900.          End,
  901.       End;
  902.       if (data->GUI.WI)
  903.       {
  904.          DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
  905.          SetHelp(data->GUI.ST_FNAME,            MSG_HELP_FO_ST_FNAME            );
  906.          SetHelp(data->GUI.TX_FPATH,            MSG_HELP_FO_TX_FPATH            );
  907.          SetHelp(data->GUI.ST_MAXAGE,           MSG_HELP_FO_ST_MAXAGE           );
  908.          SetHelp(data->GUI.CY_FMODE,            MSG_HELP_FO_CY_FMODE            );
  909.          SetHelp(data->GUI.CY_FTYPE,            MSG_HELP_FO_CY_FTYPE            );
  910.          SetHelp(data->GUI.CY_SORT[0],          MSG_HELP_FO_CY_SORT0            );
  911.          SetHelp(data->GUI.CY_SORT[1],          MSG_HELP_FO_CY_SORT1            );
  912.          SetHelp(data->GUI.CH_REVERSE[0],       MSG_HELP_FO_CH_REVERSE          );
  913.          SetHelp(data->GUI.CH_REVERSE[1],       MSG_HELP_FO_CH_REVERSE          );
  914.          SetHelp(data->GUI.ST_MLPATTERN,        MSG_HELP_FO_ST_MLPATTERN        );
  915.          SetHelp(data->GUI.ST_MLADDRESS,        MSG_HELP_FO_ST_MLADDRESS        );
  916.          SetHelp(data->GUI.ST_MLFROMADDRESS,    MSG_HELP_FO_ST_MLFROMADDRESS    );
  917.          SetHelp(data->GUI.ST_MLREPLYTOADDRESS, MSG_HELP_FO_ST_MLREPLYTOADDRESS );
  918.          SetHelp(data->GUI.CY_MLSIGNATURE,            MSG_HELP_WR_RA_SIGNATURE                 );
  919.  
  920.          DoMethod(data->GUI.BT_MOVE  ,MUIM_Notify,MUIA_Pressed             ,FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_MoveHook);
  921.          DoMethod(bt_okay            ,MUIM_Notify,MUIA_Pressed             ,FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_SaveHook);
  922.          DoMethod(bt_cancel          ,MUIM_Notify,MUIA_Pressed             ,FALSE         ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_CloseHook);
  923.          DoMethod(data->GUI.WI       ,MUIM_Notify,MUIA_Window_CloseRequest ,TRUE          ,MUIV_Notify_Application,2,MUIM_CallHook,&FO_CloseHook);
  924.          return data;
  925.       }
  926.       free(data);
  927.    }
  928.    return NULL;
  929. }
  930. ///
  931.  
  932.